﻿using Heyo.Class.Helper;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Threading;

namespace Heyo
{
    public class WindowPlus : Window
    {
        public IntPtr Handle { get; private set; }

        private readonly Border _shadowBorder = new Border
        {
            BorderThickness = new Thickness(4),
            Background = new SolidColorBrush(Colors.Transparent),
            BorderBrush = new SolidColorBrush(Colors.Black),
            Effect = new BlurEffect()
        };

        private readonly Window _aeroLayer = new Window
        {
            Opacity = 0,
            Background = new SolidColorBrush(Colors.Transparent),
            AllowsTransparency = true,
            WindowStyle = WindowStyle.None
        };
        /*private Image imageCache = new Image();
        private Window entranceWindow = new Window()
        {
            AllowsTransparency = true,
            WindowStyle = WindowStyle.None,
            Background = new SolidColorBrush(Colors.Transparent),
        };*/
        private readonly Window _shadowLayer = new Window
        {
            Opacity = 0,
            Focusable = false,
            Background = new SolidColorBrush(Colors.Transparent),
            //ShowInTaskbar = false,
            AllowsTransparency = true,
            WindowStyle = WindowStyle.None
        };
        public WindowPlus()
        {
            Dispatcher.CurrentDispatcher.Invoke(() =>
            {
                Opacity = 0;
                Loaded += WindowPlus_Loaded;
                Handle = new WindowInteropHelper(this).Handle;
                ShowInTaskbar = false;
                _shadowLayer.Content = _shadowBorder;
            });

            //base.PreviewMouseUp += (s, e) =>
            //{
            //    //Console.WriteLine("up");
            //    if (disabledAero)
            //    {
            //        AcrylicHelper.EnableAcrylic(_aeroLayer, UseAeroShadow);
            //        disabledAero = false;
            //    }
            //};


            //entranceWindow.Content = imageCache;
            //entranceWindow.Show();
        }
        bool disabledAero = true;
        private void WindowPlus_Loaded(object sender, RoutedEventArgs e)
        {
            UpdateLayerSize();
            UpdateLayerLocation();
            SizeChanged += WindowPlus_SizeChanged;
            //WindowStyleHelper.SetOpacity(this, 0.6);
            


            if (SystemHelper.IsWindow10 && Aero)
            {
                _aeroLayer.Show();
                Owner = _aeroLayer;
                AcrylicHelper.EnableAcrylic(_aeroLayer, UseAeroShadow);
                MouseMove += (s, ee) =>
                {
                    if (!disabledAero) return;
                    AcrylicHelper.EnableAcrylic(_aeroLayer, UseAeroShadow);
                    disabledAero = false;
                };
                if (!UseAeroShadow)
                {
                    SetShadowRadius(ShadowRadius);
                    SetShadowOpacity(ShadowOpacity);
                    _shadowLayer.Show();
                    _aeroLayer.Owner = _shadowLayer;
                }
            }
            else
            {
                SetShadowRadius(ShadowRadius);
                SetShadowOpacity(ShadowOpacity);
                _shadowLayer.Show();
                Owner = _shadowLayer;
                
            }

            switch (WindowEntrance)
            {
                case WindowEntrance.Fade:
                {
                    var showAnimation = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(WindowEntranceTime)));
                    showAnimation.CurrentTimeInvalidated += (s, e2) => {
                        WindowStyleHelper.SetOpacity(_aeroLayer, Opacity);
                    };
                    showAnimation.Completed += (s, e2) => { WindowStyleHelper.SetOpacity(_aeroLayer, Opacity); };
                    BeginAnimation(OpacityProperty, showAnimation);
                    break;
                }
                case WindowEntrance.None:
                    Opacity = 1;
                    _shadowLayer.Opacity = 1;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            

            Focus();
        }
        private void WindowPlus_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            UpdateLayerSize();
            OnLocationChanged(new EventArgs());
        }

        private void UpdateLayerLocation()
        {

            _aeroLayer.Left = Left;
            _aeroLayer.Top = Top;
            _shadowLayer.Left = Left - ShadowRadius;
            _shadowLayer.Top = Top - ShadowRadius;

            if (!disabledAero)
            {
                AcrylicHelper.DisableAcrylic(_aeroLayer);
                //AcrylicHelper.EnableAcrylic(_aeroLayer,UseAeroShadow,true);
                disabledAero=true;
            }
                
        }

        protected void UpdateLayerSize()
        {
            _aeroLayer.Width = ActualWidth;
            _aeroLayer.Height = ActualHeight;
            _shadowLayer.Width = ActualWidth + ShadowRadius * 2;
            _shadowLayer.Height = ActualHeight + ShadowRadius * 2;
        }
        protected override void OnLocationChanged(EventArgs e)
        {
            UpdateLayerLocation();
            base.OnLocationChanged(e);
        }
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            _shadowLayer.Opacity = Opacity;
            base.OnPropertyChanged(e);
        }
        public static readonly DependencyProperty AeroProperty =
            DependencyProperty.Register(
                "Aero",
                typeof(bool),
                typeof(WindowPlus),
                new PropertyMetadata(false)
            );

        /// <summary>
        /// 是否启用Aero
        /// </summary>
        [Category("样式")]
        public bool Aero
        {
            get => (bool)GetValue(AeroProperty);
            set
            {
                SetValue(AeroProperty, value);
                if (/*SystemHelper.IsWindow10*/true)
                {
                    if (value)
                    {
                        AcrylicHelper.EnableAcrylic(_aeroLayer, UseAeroShadow);
                    }
                    else
                    {
                        AcrylicHelper.DisableAcrylic(_aeroLayer);
                    }
                }
            }
        }
        public static readonly DependencyProperty ShadowProperty =
            DependencyProperty.Register(
                "Shadow",
                typeof(bool),
                typeof(WindowPlus),
                new PropertyMetadata(true)
            );
        /// <summary>
        /// 是否启用Aero
        /// </summary>
        [Category("样式")]
        public bool UseAeroShadow
        {
            get => (bool)GetValue(ShadowProperty);
            set => SetValue(ShadowProperty, value);
        }
        public static readonly DependencyProperty ShadowRadiusProperty =
            DependencyProperty.Register(
            "ShadowRadius",
            typeof(int),
            typeof(WindowPlus),
            new PropertyMetadata(14)
        );
        /// <summary>
        /// 阴影的半径
        /// </summary>
        [Category("样式")]
        public int ShadowRadius
        {
            get => (int)GetValue(ShadowRadiusProperty);
            set
            {
                SetValue(ShadowRadiusProperty, value);
                SetShadowRadius(value);
            }
        }



        public static readonly DependencyProperty ShadowOpacityProperty =
            DependencyProperty.Register(
            "ShadowOpacity",
            typeof(double),
            typeof(WindowPlus),
            new PropertyMetadata(0.2)
        );
        /// <summary>
        /// 阴影的浓度
        /// </summary>
        [Category("样式")]
        public double ShadowOpacity
        {
            get => (double)GetValue(ShadowOpacityProperty);
            set
            {
                SetValue(ShadowOpacityProperty, value);
                SetShadowOpacity(value);
            }
        }

        public static readonly DependencyProperty WindowEntranceProperty =
            DependencyProperty.Register(
            "WindowEntrance",
            typeof(WindowEntrance),
            typeof(WindowPlus),
            new PropertyMetadata(WindowEntrance.None)
        );
        /// <summary>
        /// 入场方式
        /// </summary>
        [Category("样式")]
        public WindowEntrance WindowEntrance
        {
            get => (WindowEntrance)GetValue(WindowEntranceProperty);
            set => SetValue(WindowEntranceProperty, value);
        }

        public static readonly DependencyProperty WindowEntranceTimeProperty =
            DependencyProperty.Register(
            "WindowEntranceTime",
            typeof(double),
            typeof(WindowPlus),
            new PropertyMetadata(0.4)
        );
        /// <summary>
        /// 入场动画时间
        /// </summary>
        [Category("样式")]
        public double WindowEntranceTime
        {
            get => (double)GetValue(WindowEntranceTimeProperty);
            set => SetValue(WindowEntranceTimeProperty, value);
        }

        private void SetShadowRadius(int radius)
        {
            _shadowBorder.Margin = new Thickness(ShadowRadius);
            ((BlurEffect) _shadowBorder.Effect).Radius = radius;
        }

        private void SetShadowOpacity(double opacity)
        {
            _shadowBorder.Opacity = opacity;
        }
        public new void Close()
        {
            switch (WindowEntrance)
            {
                case WindowEntrance.Fade:
                {
                    var closeAnimation = new DoubleAnimation(1, 0, new Duration(TimeSpan.FromSeconds(WindowEntranceTime)));
                    closeAnimation.CurrentTimeInvalidated += (s, e) => {
                        WindowStyleHelper.SetOpacity(_aeroLayer, Opacity);
                    };
                    closeAnimation.Completed += (s, e) => {
                        base.Close();
                        _shadowLayer.Close();
                        _aeroLayer.Close();
                    };
                    BeginAnimation(OpacityProperty, closeAnimation);
                    break;
                }
                case WindowEntrance.None:
                    base.Close();
                    _shadowLayer.Close();
                    _aeroLayer.Close();
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    }
}
